package p2p;

import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.rmi.NotBoundException;
import java.rmi.RemoteException;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;

import server.Message;

public class NeighborList{
	private List<Peer> nlist = new ArrayList<Peer>();
	private int maxNeighbors;
	private PeerPool peerPool;
	private Peer thisPeer;

	public NeighborList(int maxNeighbors, PeerPool peerPool, Peer thisPeer) {
		this.maxNeighbors = maxNeighbors;
		this.peerPool = peerPool;
		this.thisPeer = thisPeer;
	}

	public void update() {
		Registry registry;
		Message rmiServer;
		
		List<Peer> plist = peerPool.getPeerPoolList();
		Collections.sort(plist);

		if(!plist.isEmpty()) { //plist not empty?
			for(Peer p : plist) {
				//Create neighbors / manage neighbors
				try {
					//Is neighbor?
					registry = LocateRegistry.getRegistry(p.getIp(), p.getPort()); //get the “registry” 
					rmiServer = (Message)(registry.lookup(Config.ServerName)); //look up remote object
					
					boolean isNeigbor = rmiServer.isNeighbor(thisPeer);//call remote method
					if(isNeigbor) { //is neighbor
						//do nothing
					} else { //is not neighbor
						nlist.remove(p);
						
						if(nlist.size() >= maxNeighbors) { //no more space for neighbors
							continue;
						}
						
						//Create neighbor
						registry = LocateRegistry.getRegistry(p.getIp(), p.getPort()); //get the “registry” 
						rmiServer = (Message)(registry.lookup(Config.ServerName)); //look up remote object
						Peer newNeighbor = rmiServer.helloNeighbor(thisPeer);//call remote method
						
						//Add to nlist
						if(newNeighbor == null) { //No room for a neighbor at remote peer
							continue;
						} else {
							nlist.add(newNeighbor);
						}
					}
				} catch (NotBoundException e) {
					e.printStackTrace();
				} catch (RemoteException e) {
					e.printStackTrace();
				}
			}
			
			//Delete non existing neighbors
			Iterator<Peer> itr = nlist.iterator();
		    while (itr.hasNext()) {
		    	Peer p = itr.next();
		    	if(plist.contains(p)) {
					//do nothing
				} else {
					itr.remove();
				}
		    }
		} else {
			nlist.clear();
		}
	}

	public List<Peer> getNlist() {
		return Collections.unmodifiableList(nlist); //TODO: does NeigborList contain thisPeer ???
	}

	public Peer helloNeighbor(Peer fromPeer) {
		if(nlist.size() < maxNeighbors){ //is there room for more neighbors?
			nlist.add(fromPeer); //add peer to own list of neighbors
			return thisPeer;
		}else{
			return null;
		}
	}
	
	public boolean isNeighbor(Peer fromPeer) {
		if(getNlist().contains(fromPeer)) {
			return true;
		}
		return false;
	}
	
	public boolean writeToFile(String s, File f) {
		FileWriter out;
		try {
			out = new FileWriter(f);
			out.write(s);
			out.close();
			
			return true;
		} catch(IOException e) {
			return false;
		}
	}

	/*
	 * Private methods
	 */
}
